<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Entity_Core_Collection {

    protected $_where = '';
    protected $_having = '';
    
    // the entity set these values
    protected $_entity = null;
    protected $_resource = null;
    
	public function __construct() {	}
	
	public function setEntity($entity) {
		$this->_entity = $entity;
		$this->_resource = $entity->getResource();
		$this->_resource->from($entity->getEntityName());
		return $this;
	}

	public function getSize() {
		if (!empty($this->_where)) {
			$this->_resource->where(rtrim($this->_where, ' AND '));
		}
		return $this->_resource->count_all_results();
	}
	
	public function getSelect($offset = null, $limit = null) {
		$result = array();
		if (!empty($this->_where)) {
			$this->_resource->where(rtrim($this->_where, ' AND '));
		}
		
		$query = $this->_resource->get('', $limit, $offset);
		foreach ($query->result_array() as $row) {
			array_push($result, $this->_entity->createEntity($row));
		}
		return $result;
	}
	
    public function addAttributeToSelect($name) {
    	$this->_resource->select($name);
    	return $this;
    }
    
	public function groupByAttribute($attribute) {
		$this->_resource->group_by($attribute);
		return $this;
	}
	
    public function having() {
    	if (func_num_args() < 1) throw new Exception('No condition in filter');
    	$result = $this->getConditionString(func_get_args());
    	if (!empty($result)) $this->_having .= '('.$result . ') AND ';
    	return $this;
    }
	
	public function addAttributeToSort($attribute, $dir='asc') {
		$this->_resource->order_by($attribute, $dir);
		return $this;
	}
	
    public function addFieldToFilter() {
    	if (func_num_args() < 1) throw new Exception('No condition in filter');
    	$result = $this->getConditionString(func_get_args());
    	if (!empty($result)) $this->_where .= '('.$result . ') AND ';
    	return $this;
    }
	
    protected function getConditionString() {
    	$result = '';
    	$tmp = func_get_args();
    	$args = $tmp[0]; 

		switch (gettype($args[0])) {
    		case 'string':
    			switch (gettype($args[1])) {
    				case 'string':
    					$result = $this->equalCond($args[0], $args[1]);
    					break;
    				case 'array':
    					$result = $this->operatorCond($args[0], $args[1]);
    					break;
    			}
    			break;
    			
    		case 'array':
    			foreach ($args as $cond)
    				$result .= $this->getConditionString($cond) . ' OR ';
    			$result = rtrim($result, ' OR ');
				break;
    	}
    	return $result;
    }
    
	protected function equalCond($key, $value) {
		return "$key = '$value'";
	}
	
	protected function operatorCond($key, $operator) {
		$result = '';
		$tmp = array_keys($operator);
		$opKey = $tmp[0];
		$value = $operator[$opKey];
		
		switch ($opKey) {
			case 'eq':
				$result = $this->equalCond($key, $value);
				break;
			case 'neq':
				$result = "$key != '$value'";
				break;
			case 'like':
				$result = "$key LIKE '$value'";
				break;
			case 'nlike':
				$result = "$key NOT LIKE '$value'";
				break;
			case 'bwn':
				$result = "$key BETWEEN $value[0] AND $value[1]";
				break;
			case 'in':
				$ins = '(';
				foreach ($value as $v) $ins .= "$v,";
				$ins = rtrim($ins, ',') . ')';
				$result = "$key IN $ins";
				break;
			case 'nin':
				$ins = '(';
				foreach ($value as $v) $ins .= "$v,";
				$ins = rtrim($ins, ',') . ')';
				$result = "$key NOT IN $ins";
				break;
			case 'null':
				$result = "$key IS NULL";
				break;
			case 'notnull':
				$result = "$key IS NOT NULL";
				break;
			case 'gt':
				$result = "$key > $value";
				break;
			case 'lt':
				$result = "$key < $value";
				break;
			case 'gteq':
				$result = "$key >= $value";
				break;
			case 'lteq':
				$result = "$key <= $value";
				break;
		}
		return $result;
	}
}
